﻿using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.Data;
using System.Linq;
using System.Reflection;
using System.Text;

namespace Zgq.CommonTools
{
    public static class PublicHelper
    {
        public static void GetObjectPropertyCopy<T>(T destT, T sourceT, bool isNotCopyDetail)
        {

            if (destT == null) throw new Exception("目标对象不能为空！");
            if (sourceT == null) throw new C5CopySourceIsNullException("源对象不能为空！");

            Type type = destT.GetType();
            Type tempType = sourceT.GetType();

            if (type != tempType) throw new Exception("对象类型不一致");

            PropertyInfo[] properties = type.GetProperties();//BindingFlags.Instance | BindingFlags.Public | System.Reflection.BindingFlags.DeclaredOnly);

            foreach (PropertyInfo info in properties)
            {
                if (info.Name.StartsWith("ChildrenListObject"))
                {
                    if (isNotCopyDetail) return;
                    List<T> models = info.GetValue(sourceT, null) as List<T>;
                    if (models == null) continue;

                    List<T> destTs = new List<T>();
                    foreach (var item in models)
                    {
                        T _t = (T)Activator.CreateInstance(item.GetType(), null);
                        GetObjectPropertyCopy(_t, item, isNotCopyDetail);
                        destTs.Add(_t);
                    }
                    info.SetValue(destT, destTs, null);
                }
                else
                {
                    object o = info.GetValue(sourceT, null);
                    info.SetValue(destT, o, null);
                }
            }
        }

        /// <summary>
        /// List集合转DataTable
        /// </summary>
        /// <typeparam name="T">实体类型</typeparam>
        /// <param name="list">传入集合</param>
        /// <param name="isStoreDB">是否存入数据库DateTime字段，date时间范围没事，取出展示不用设置TRUE</param>
        /// <returns>返回datatable结果</returns>
        public static DataTable ListToTable<T>(List<T> list, bool isStoreDB = true)
        {
            Type tp = typeof(T);
            PropertyInfo[] proInfos = tp.GetProperties();
            DataTable dt = new DataTable();
            foreach (var item in proInfos)
            {
                dt.Columns.Add(item.Name); //添加列明及对应类型
            }
            foreach (var item in list)
            {
                DataRow dr = dt.NewRow();
                foreach (var proInfo in proInfos)
                {
                    object obj = proInfo.GetValue(item, null);
                    if (obj == null)
                    {
                        continue;
                    }
                    //if (obj != null)
                    // {
                    if (isStoreDB && proInfo.PropertyType == typeof(DateTime) && Convert.ToDateTime(obj) < Convert.ToDateTime("1753-01-01"))
                    {
                        continue;
                    }
                    // dr[proInfo.Name] = proInfo.GetValue(item);
                    dr[proInfo.Name] = obj;
                    // }
                }
                dt.Rows.Add(dr);
            }
            return dt;
        }

        #region   DataRow转为实体类
        /// <summary>
        /// DataRow转为实体类
        /// </summary>
        /// <typeparam name="T">实体类类型</typeparam>
        /// <param name="rows">DataRow</param>
        /// <returns>T</returns>
        public static List<T> DataRowsToList<T>(List<DataRow> rows)
        {
            Type t = typeof(T);

            List<T> tempList = new List<T>();

            PropertyInfo[] propertypes = propertypes = t.GetType().GetProperties();

            string tempName = string.Empty;

            var obj = Activator.CreateInstance<T>();

            foreach (var item in rows)
            {
                foreach (PropertyInfo pro in propertypes)
                {
                    tempName = pro.Name;
                    if (item.Table.Columns.Contains(tempName))
                    {
                        object value = item[tempName];
                        if (value.GetType() == typeof(System.DBNull))
                        {
                            value = null;
                        }
                        pro.SetValue(t, value, null);
                    }
                }

                tempList.Add(obj);
            }

            return tempList;
        }
        #endregion


        #region 获取主键

        /// <summary>
        /// 获取主键集合
        /// </summary>
        /// <param name="tp"></param>
        /// <returns></returns>
        public static string[] GetPrimaryKeysByType(this Type tp)
        {
            if (tp == null)
                return null;

            //新实体
            var attr = tp.GetCustomAttributes(typeof(C5ClassModelAttribute), true);
            if (attr.Count() == 0)
                attr = tp.BaseType.GetCustomAttributes(typeof(C5ClassModelAttribute), true);

            //EF实体
            if (attr.Count() == 0)
            {
                var properties = tp.GetProperties().Where(p => p.GetCustomAttributes(typeof(KeyAttribute), false).Length > 0).ToList();
                if (properties == null || properties.Count == 0)
                    return null;

                return properties.Select(x => x.Name).ToArray();
            }

            var C5ClassModel = attr[0] as C5ClassModelAttribute;
            if (string.IsNullOrWhiteSpace(C5ClassModel.PrimaryKeys))
                return null;

            return C5ClassModel.PrimaryKeys.Split(',');
        }

        /// <summary>
        /// 获取主键集合
        /// </summary>
        /// <param name="_t"></param>
        /// <returns></returns>
        public static string[] GetPrimaryKeys<T>(this T _t) where T : class
        {
            if (_t == null)
                return null;

            Type tp = typeof(T);

            if (tp == null) return null;

            var attr = tp.GetCustomAttributes(typeof(C5ClassModelAttribute), true);
            if (attr.Count() == 0)
                attr = tp.BaseType.GetCustomAttributes(typeof(C5ClassModelAttribute), true);

            if (attr.Count() == 0)
                return null;

            var C5ClassModel = attr[0] as C5ClassModelAttribute;
            if (string.IsNullOrWhiteSpace(C5ClassModel.PrimaryKeys))
                return null;

            return C5ClassModel.PrimaryKeys.Split(',');
        }

        #endregion
    }
}
